<#
    .AUTHOR
        cw50406@imcnam.ssmb.com  
    .GROUP
        RPA AA STE Support Team(dl.gt.cn.cstc.rpa.aa.ste@imcnam.ssmb.com)
    .VERSION
        2.0
    .Synopsis
        Restart RDC Sessions
    .DESCRIPTION
        This script is used to restart RDC sessions in working days as described in below WIKI
        https://cedt-confluence.nam.nsroot.net/confluence/display/169794A/Steps+to+Refresh+RDC+Sessions
    .EXAMPLE
        .\RestartRDCSessions.ps1
        Restart RDC Sessions without providing the end user, which will be based on the env
    .EXAMPLE
        .\RestartRDCSessions.ps1 cw50406
        Restart RDC Sessions in cw50406 user sessions.
    .Update
        09/11/2017--optimize code with more clear comments structure
        08/29/2017--optimize email sending code with domain,env,node,running result ...
        08/17/2017--send notifications email to team
        08/01/2017--Optimize code structure
#>
param(
	[Parameter(Mandatory=$False)]      
	[string]$restart_rdc_sessions_user                        # in which user to restart rdc sessions
)
#<---------------------------------- initilize functions and parameters
$start_time=(Get-Date).ToString("HH:mm:ss")                           # the script start time, to be used in the email sending
$this_path = Split-Path -Parent ($MyInvocation.MyCommand.Definition)  # the full directory path of this script
$this_user=$env:username                                              # the user which is running this script
$this_machine=$env:computername                                       # the computer name that the scripts is in
$restart_rdc_sessions_user_domain="nam"                               # the default domain of the run rdc user
. "$this_path\functions.ps1"                                          # invoke all the fucntions to the powershell script
#<---------------------------------- initilize powershell log file path and name
$powershell_log_path = $this_path.Replace('\scripts\','\logs\') ; New-FileFolder $powershell_log_path -d
$powershell_log_file="$powershell_log_path\$((Get-Date).ToString('yyyyMMdd_HHmmss'))_RestartRDCSessions.log"
Write-Log Normal "----------------START OF SCRIPT----------------" $powershell_log_file
#<---------------------------------- initilize autosys log file path and name
$autosys_log_path = "C:\Program Files\CA\Workload Automation AE\SystemAgent\WA1_AGENT\log\RestartRDCSessions" ; New-FileFolder $autosys_log_path -d
$autosys_error_log_file="$autosys_log_path\err.log" ; $autosys_out_log_file  ="$autosys_log_path\out.log" 
$autosys_error_log_file,$autosys_out_log_file|%{New-FileFolder $_}
#<---------------------------------- check the env to tell which user to run
If( !$PSBoundParameters.ContainsKey('restart_rdc_sessions_user') ){ # if $restart_rdc_sessions_user has not beed provided, using default one(aaadmin(_p))
	$restart_rdc_sessions_user = Switch -regex ($this_machine.Substring(7,3).ToLower()){ # check computer name to tell the env
	    "p2n|c2n|e2n"{"aaadmin_p";break} # PROD,COB,PTE
	    default{"aaadmin"}
	}
}else{
	If( [string]::IsNullOrWhiteSpace($restart_rdc_sessions_user)){ # exit script
		Stop-WithError ": $restart_rdc_sessions_user is not valid(either null or empty)" $powershell_log_file $this_user $start_time;return
	}else{
		If( $restart_rdc_sessions_user -like "*\*" ){
		    $restart_rdc_sessions_user_domain,$restart_rdc_sessions_user=$restart_rdc_sessions_user.split('\')
		}
	}
}
#<---------------------------------- as logfile was created by admin user, set the logfile access so that $restart_rdc_sessions_user can write log to it
Write-Log Normal "Trying to add user $restart_rdc_sessions_user write access to log files" $powershell_log_file
$this_path,$powershell_log_file,$autosys_log_path|%{Set-FileAccess $_ "$restart_rdc_sessions_user_domain\$restart_rdc_sessions_user"}
Write-Log Normal "------------------------------------------------------------------" $autosys_error_log_file
If( !(query user $restart_rdc_sessions_user 2>$null) ){ # exit script and send alert email
	Stop-WithError ": Not found $restart_rdc_sessions_user logged in $this_machine." $powershell_log_file $restart_rdc_sessions_user $start_time ; return
}
#<---------------------------------- check existence of ServersConfiguration.csv
$servers_configuration_csv="C:\Users\$restart_rdc_sessions_user\RDC Monitor\ServersConfiguration.csv"
Write-Log Normal "Checking existence of $servers_configuration_csv" $powershell_log_file
If( !(test-path $servers_configuration_csv) ){
	Stop-WithError ": Not found $servers_configuration_csv" $powershell_log_file $restart_rdc_sessions_user $start_time ; return
}else{
	$config_list=@() ; Import-Csv $servers_configuration_csv -ea 0|%{$config_list+=$_.computerName}
	If( $config_list.count -eq 0 ){ # exit script and send alert email
		Stop-WithError ": Not found VDI in $servers_configuration_csv" $powershell_log_file $restart_rdc_sessions_user $start_time ; return
	}
}
Write-Log Normal "There are total $($config_list.count) VDIs in config file." $powershell_log_file
#<----------------------------------  Kill all the other rdcmon processes with only one latest started process started by $restart_rdc_sessions_user left 
Write-Log Normal "Trying to kill all the other rdcmon processes with only latest one started by $restart_rdc_sessions_user" $powershell_log_file
# logoff other user except $restart_rdc_sessions_user
If( ($not_of_user_session_id=quser|?{$_ -inotmatch $restart_rdc_sessions_user -and $_ -inotmatch 'USERNAME' }|%{($_ -split ' +')[2]}) -ne $null ){
	Foreach( $id in $not_of_user_session_id){
		logoff $id 2>$null
	}
	$mail_sent=$false
	Do{
		$not_of_user_session=quser|?{$_ -inotmatch $restart_rdc_sessions_user -and $_ -inotmatch 'USERNAME' }
		sleep 1;$loop_cnt++
		If( $loop_cnt -gt 1799){ # exit script and send alert email
            quser 2>$null |Out-File -FilePath $powershell_log_file -Append -Encoding utf8 -Force 
			Stop-WithError ": Still found other user logged 30mins later after trying to logoff it." $powershell_log_file $restart_rdc_sessions_user $start_time ; return
		}elseif(!$mail_sent ){  # exit script and send alert email
			If(  $loop_cnt -gt 599 ){
                quser 2>$null |Out-File -FilePath $powershell_log_file -Append -Encoding utf8 -Force 
				$body_template="There is an error when running the RDC Session Refresh process`r`n`nError: Still found other user logged 10mins later after trying to logoff it."
				Send-Mailtoteam $restart_rdc_sessions_user "WARNING" ": Unable To Logoff User" $body_template $powershell_log_file $start_time
			    $mail_sent=$true
			}
		}
	}While( $not_of_user_session -ne $null)

}
#<---------------------------------- close old rdcmon.exe process
SCHTASKS /CREATE /RU $restart_rdc_sessions_user /tn close_old_rdc_process /sc ONCE  /st (get-date).tostring("HH:mm") /F `
/tr "powershell.exe -WindowStyle Hidden -Executionpolicy unrestricted '$this_path\close_old_rdc_process.ps1 $powershell_log_file $start_time'" 1>$null 2>&1 
SCHTASKS /run /tn close_old_rdc_process 1>$null 2>&1 ; $task_finish=$false;$loop_cnt=0 ; $mail_sent=$false
Do{
	If( (SCHTASKS /QUERY /TN close_old_rdc_process 2>$null) -imatch "Ready" ){
		SCHTASKS /DELETE /TN close_old_rdc_process /F 1>$null 2>&1
		$task_finish=$true;break
	}
	sleep 1;$loop_cnt++
	If( $loop_cnt -gt 1799){ # exit script and send alert email
		Stop-WithError ": Task close_old_rdc_process is still running 30mins later after it's been started!" $powershell_log_file $restart_rdc_sessions_user $start_time ; return
	}elseif(!$mail_sent ){  # exit script and send alert email
		If( $loop_cnt -gt 599 ){
			$body_template="There is an error when running the RDC Session Refresh process`r`n`nError: Task close_old_rdc_process is still running 10mins later after it's been started!"
			Send-Mailtoteam $restart_rdc_sessions_user "WARNING" ": Task Still Running" $body_template $powershell_log_file $start_time
		    $mail_sent=$true
		}
	}
}While( !$task_finish )
If( (cat $powershell_log_file -ea 0) -imatch 'END OF SCRIPT' ){exit}
#<---------------------------------- start to remove VDI login ok button
$remove_login_ok_button_action={
	param($vdi,$cnt,$powershell_log_file)
	If(Test-Connection $vdi -quiet -count 1 -ErrorAction Ignore){ 
		Try{
			reg delete "\\$vdi\HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system\" /v legalnoticecaption /f 1>$null 2>&1
		}Catch{
		    If( $_.exception -like "*Access is denied*" ){Write-Log Error "$cnt-$vdi-Access denied to remove loginOK button value" $powershell_log_file
		    }else{reg delete "\\$vdi\HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system\" /v legalnoticetext /f 1>$null 2>&1}
		}Finally{}
	}else{ # VDI is offline
		Write-Log Error "$cnt-$vdi-is Offline" $powershell_log_file
	}
}
#<---------------------------------- Using parallel threads to setup registry at the same time
Write-Log Normal "Starting to remove VDI login OK Button..." $powershell_log_file
Start-BulkThreads $config_list $remove_login_ok_button_action $powershell_log_file
Write-Log Normal "Trying to stop mstsc process..." $powershell_log_file
#<---------------------------------- close all opened RDC sessions and wait 12 mins
If( ($mstsc_process=Get-Process mstsc -ErrorAction Ignore) -ne $null ){
	# Use system account to kill mstsc process in case access denied.
    SCHTASKS /CREATE /RU System /NP /RL HIGHEST /tn close_mstsc_process /sc ONCE  /st (get-date).tostring("HH:mm") /F `
	/tr "powershell.exe -Executionpolicy unrestricted -command '&{Get-Process mstsc|kill -force}'" 1>$null 2>&1 
	SCHTASKS /run /tn close_mstsc_process 1>$null 2>&1 ; $task_finish=$false;$loop_cnt=0 ; $mail_sent=$false
	Do{
	    If( (SCHTASKS /QUERY /TN close_mstsc_process 2>$null) -imatch "Ready" ){
			SCHTASKS /DELETE /TN close_mstsc_process /F 1>$null 2>&1
	        $task_finish=$true;break
	    }
		sleep 1;$loop_cnt++
		If( $loop_cnt -gt 1799){ # exit script and send alert email
		    Stop-WithError ": Task close_mstsc_process is still running 30mins later after it's been started!" $powershell_log_file $restart_rdc_sessions_user $start_time ; return
		}elseif(!$mail_sent){  # exit script and send alert email
			If(  $loop_cnt -gt 599  ){
				$body_template="There is an error when running the RDC Session Refresh process`r`n`nError: Task close_mstsc_process is still running 10mins later after it's been started!"
				Send-Mailtoteam $restart_rdc_sessions_user "WARNING" ": Task Still Running" $body_template $powershell_log_file $start_time
			    $mail_sent=$true
			}
		}
	}While( !$task_finish )
}else{
	Write-Log Error "Not found the mstsc.exe process" $powershell_log_file
}
Write-Log Normal "Start waiting 12 mins" $powershell_log_file ; sleep 720
#<---------------------------------- mstsc window title can only be found by the logged user itself
SCHTASKS /CREATE /RU $restart_rdc_sessions_user /tn check_connected_rdc_sessions /sc ONCE  /st (get-date).tostring("HH:mm") /F `
/tr "powershell.exe -WindowStyle Hidden -Executionpolicy unrestricted '$this_path\check_connected_rdc_sessions.ps1 $powershell_log_file $start_time'" 1>$null 2>&1 
SCHTASKS /run /tn check_connected_rdc_sessions 1>$null 2>&1 ; $task_finish=$false;$loop_cnt=0; $mail_sent=$false
Do{
	If( (SCHTASKS /QUERY /TN check_connected_rdc_sessions 2>$null) -imatch "Ready" ){
		SCHTASKS /DELETE /TN check_connected_rdc_sessions /F 1>$null 2>&1
		$task_finish=$true;break
	}
	sleep 1;$loop_cnt++
	If( $loop_cnt -gt 1799){ # exit script and send alert email
		Stop-WithError ": Task check_connected_rdc_sessions is still running 30mins later after it's been started!" $powershell_log_file $restart_rdc_sessions_user $start_time ; return
	}elseif(!$mail_sent){  # exit script and send alert email
		If(  $loop_cnt -gt 599  ){
			$body_template="There is an error when running the RDC Session Refresh process`r`n`nError: Task check_connected_rdc_sessions is still running 10mins later after it's been started!"
			Send-Mailtoteam $restart_rdc_sessions_user "WARNING" ": Task Still Running" $body_template $powershell_log_file $start_time
		    $mail_sent=$true
		}
	}
}While( !$task_finish )